package com.mach.platform.service.js.iot;

import com.mach.platform.domain.Response;
import com.mach.platform.service.js.JsService;
import com.mach.platform.util.SqlHelper;
import com.mach.platform.util.U;
import com.mach.platform.utils.DateUtil;
import com.mach.platform.utils.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.DateTimeUtils;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import java.io.InputStream;
import java.io.PrintStream;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 *  设备操作类，这里把一些java操作对象放到js中供调用
 */
@Slf4j
public class SimpleModelDev extends HashMap<Object,Object> implements GeneralModelDev, Runnable{
    private final IOTJsService iot;
    private final SqlHelper sql;
    private final JsTimeTools jsTimeTools;
    //    private Map<Object,Object> props = new HashMap<Object,Object>();
    private boolean isRun = false;
    private String typeJS = null;
    private String devJS = null;
    private Integer isRunTypeJS = 0;
    private Integer isRunDevJS = 0;
    private ScriptEngine eng = null;
    private StringBuilder devFullJs;


    public SimpleModelDev(Map<String, Object> devInfo, IOTJsService iot){
//        this.putAll(devInfo);
        this.iot = iot;
        this.sql = iot.sqlHelper();
        jsTimeTools = new JsTimeTools();
    }

    @Override
    public Integer getId(){
        // 启动报错         java.lang.Long cannot be cast to java.lang.Integer
        return ((Number)this.get("devId")).intValue();
    }

    public void sendPick(){
        if(this.eng != null){
            try {
                this.eng.eval("if(dev.pick)dev.pick();");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void updateDevInfo(Map<String, Object> devInfo) {
        this.clear();
        this.putAll(devInfo);
        initDev();

    }
    private void initDev(){
        this.eng = JsService.get().newNashornEng();
        this.eng.put("iot", this.iot);
        this.eng.put("dev", this);
        // 时间日期工具类操作
        this.eng.put("dtime", jsTimeTools);

        String devPreJs = "";

         devFullJs = new StringBuilder();

        devFullJs.append("(function(iot,dev){\n");

        try {
            InputStream stm = SimpleModelDev.class
                    .getResourceAsStream("/preDev.js");
            devPreJs = StrUtil.getCtxByStm(stm, 1024, "utf-8");
            stm.close();
//                    devPreJs = StrUtil.getCtxByFile(new File(SimpleModelDev.class.getResource("/").getPath()+
//                            "preDev.js"),1024,"utf-8");
        } catch (Exception e) {
//            e.printStackTrace();
        }

        if(devPreJs != null && !"".equals(devPreJs)){
            devFullJs.append(devPreJs).append("\n");
        }


        String devPreSelfJs = null;
        try {
            ResourceLoader resourceLoader = new DefaultResourceLoader();
            InputStream inputStream = resourceLoader.getResource("classpath:preDevSelf.js").getInputStream();
            devPreSelfJs = StrUtil.getCtxByFile(inputStream, 1024, "utf-8");
        } catch (Exception e) {
            //e.printStackTrace();
        }
        if(devPreJs != null && !"".equals(devPreJs)){
            devFullJs.append(devPreSelfJs).append("\n");
        }

        //上帝代码
        String godScript = null;
        try {
            Map<String, Object> scriptMap = this.sql.queryOne("select script from iot_dev where id=1");
            godScript = (String) scriptMap.get("script");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        if(godScript != null && !"".equals(godScript)){
            devFullJs.append(godScript).append("\n");
        }


        this.isRunTypeJS = (Integer)this.get("isRunTypeJS");
        this.typeJS = (String)this.get("typeJS");

        if(isRunTypeJS != null && isRunTypeJS == 1){
            devFullJs.append(this.typeJS).append("\n");
        }

        this.isRunDevJS = (Integer)this.get("isRunDevJS");
        this.devJS = (String)this.get("devJS");

        if(isRunDevJS != null && isRunDevJS == 1){
            devFullJs.append(this.devJS).append("\n");
        }

        //devFullJs.append("print('Hello!');\n");
        this.devFullJs.append("\n})(iot,dev);\n");

        try {
            this.eng.eval(devFullJs.toString());
        } catch (ScriptException e) {
            e.printStackTrace();
            log.error("error msg:" + e.getLocalizedMessage() + " devId=" + this.getId() + "");
        }


    }

    @Override
    public void start() {

        //this.initDev();

        if(!this.isRun){
            this.isRun = true;
            U.cachedThreadPool.execute(this);
        }
    }

    @Override
    public boolean hasStart() {
        return this.isRun;
    }

    @Override
    public void sendAction(Response resp, HashMap<String, Object> param) {
        String respName = "resp_" + Thread.currentThread().getId() + "_" + System.currentTimeMillis();
        String paramName = "param_" + Thread.currentThread().getId() + "_" + System.currentTimeMillis();

        try {
            this.eng.put(respName, resp);
            this.eng.put(paramName, param);
            this.eng.eval("if(dev && dev.action)dev.action("+respName+","+paramName+");");
            this.eng.put(respName,null);
            this.eng.put(paramName,null);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                this.eng.eval("" + respName +"=null;");
            } catch (ScriptException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void run() {

        while(this.isRun){

            try {
                //this.sendPick();
                Thread.sleep(1*1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        this.isRun = false;

    }

    /*
    创建Ctx环境
     */
    public Ctx cc(Object value){
        Ctx ctx = null;
        try {
            String jsObjName = "jsObjName_" + Thread.currentThread().getId() + "_" + System.currentTimeMillis();
            try {
                this.eng.put(jsObjName, value);
                ctx = (Ctx)this.eng.eval("Ctx.frMap("+jsObjName+");");
                this.eng.put(jsObjName,null);
            } catch (ScriptException e) {
                e.printStackTrace();
            }finally {
                try {
                    this.eng.eval("" + jsObjName +"=null;");
                } catch (ScriptException e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ctx;
    }

    public Ctx curData(String propName){
        Ctx result = null;
        try {
            Map<String, Object> data = this.sql.queryOne("select data_type propName,dValue,uptime from iot_dev_cur_data_win where 1=1 " +
                    " and id=" + this.getId() + " " +
                    " and data_type='" + propName + "' " +
                    "");
            result = this.cc(data);

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static void main(String[] args){
        System.out.println("当前classpath的URI\n" + SimpleModelDev.class.getResource("/"));
    }
}
